package com.tj.collection.task;

import com.alibaba.fastjson.JSONObject;
import com.fqgj.common.api.Response;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.DateUtil;
import com.fqgj.common.utils.StringUtils;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.kly.user.dto.UserInfoDto;
import com.kly.user.enums.UserType;
import com.kly.user.service.UserService;
import com.tj.collection.db.dao.*;
import com.tj.collection.db.entity.*;
import com.tj.collection.enums.DataReportTypeEnum;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * chatter 每日数据统计
 */
@Service
public class ChatterDataTask {

    private static Log logger = LogFactory.getLog(ChatterDataTask.class);
    @Resource
    RptCustomQuerySqlDao customQuerySqlDao;
    @Resource
    RptChatterDataPreDayDao chatterDataPreDayDao;
    @Resource
    CusomExtDao cusomExtDao;
    @Resource
    UserService userService;
    @Resource
    RptChatterOnlinePreHourDao chatterOnlinePreHourDao;
    @Resource
    ChatterConfigDao chatterConfigDao;
    @Resource
    RptUserOnlineDetailDao userOnlineDetailDao;
    /**
     * chatter 数据统计
     * 统计频率：3600s
     */
    @Scheduled(fixedDelay = 1000 * 600)
    public void chatterData() {
        final Response<List<UserInfoDto>> chatters = userService.getUserByUserType(String.valueOf(UserType.CHATTER.getType()));
        if (chatters ==null || CollectionUtils.isEmpty(chatters.getData())) {
            return;
        }
        // 初始化数据表
        initChatterData(chatters.getData());
        // 获取自定义sql
        final List<RptCustomQuerySqlEntity> customSqlList = getCustomSqlList(DataReportTypeEnum.CHATTER_DATA.getType());
        if (CollectionUtils.isEmpty(customSqlList)) {
            return;
        }

        for (RptCustomQuerySqlEntity customQuerySql : customSqlList) {
            logger.info("====name{}， sql:{}", customQuerySql.getName(), customQuerySql.getSqlText());
            final List<Map<String, Object>> records = cusomExtDao.customQuery2(customQuerySql.getSqlText());
            if (CollectionUtils.isEmpty(records)) {
                continue;
            }

            for (Map<String, Object> item : records) {
                final String updateSql = buildUpdateSql(customQuerySql, item);
                if (StringUtils.isEmpty(updateSql)) {
                    continue;
                }
                chatterDataPreDayDao.updateModelData(updateSql);
                // 只执行一次
                if (customQuerySql.getExecuteOnceFlag() == 1) {
                    break;
                }
            }
        }
    }

    /**
     * 当前在线用户数统计
     */
    @Scheduled(fixedDelay = 1000 * 120)
    public void userOnlineData() {
        final Response<List<UserInfoDto>> chatters = userService.getUserByUserType(String.valueOf(UserType.CHATTER.getType()));
        if (chatters ==null || CollectionUtils.isEmpty(chatters.getData())) {
            return;
        }

        // 添加用户在线详细信息
        addUserOnlineDetail();

        // 统计当前时段在线数据
        addUserOnlineData();
    }

    private void addUserOnlineData() {
        final List<RptCustomQuerySqlEntity> onlineSqlList = getCustomSqlList(DataReportTypeEnum.ONLINE_USER_DATA.getType());
        if (CollectionUtils.isEmpty(onlineSqlList)) {
            return;
        }
        final RptCustomQuerySqlEntity customQuerySql = onlineSqlList.get(0);
        final List<Map<String, Object>> records = cusomExtDao.customQuery2(customQuerySql.getSqlText());
        if (CollectionUtils.isEmpty(records)) {
            return;
        }

        // 获取chatter的用户在线配置
        final List<ChatterConfigEntity> allChatterConfigs = chatterConfigDao.listAllChatterConfigs();
        final Map<String, RptChatterOnlinePreHourEntity> onlineMap = buildChatterOnlineMap();

        for (Map<String, Object> item : records) {
            final boolean isExistsFlag = item.get("chatter_user_code") != null && onlineMap.containsKey(item.get("chatter_user_code").toString());
            if (isExistsFlag) {
                final RptChatterOnlinePreHourEntity existsEntity = onlineMap.get(item.get("chatter_user_code").toString());
                Integer onlineCnt = item.get("online_user_total") == null ? 0 : Integer.parseInt(item.get("online_user_total").toString());
                if (onlineCnt > existsEntity.getOnlineUserCnt()) {
                    existsEntity.setOnlineUserCnt(onlineCnt);
                    chatterOnlinePreHourDao.updateByPrimaryKey(existsEntity);
                }
            } else {
                if (item.containsKey("chatter_user_code")) {
                    RptChatterOnlinePreHourEntity onlinePreHour = new RptChatterOnlinePreHourEntity();
                    onlinePreHour.setChatterUserCode(item.get("chatter_user_code").toString());
                    onlinePreHour.setCreateDt(Integer.valueOf(cn.hutool.core.date.DateUtil.format(new Date(), "yyyyMMdd")));
                    onlinePreHour.setCreateHour(cn.hutool.core.date.DateUtil.hour(new Date(), Boolean.TRUE));
                    Integer onlineCnt = item.get("online_user_total") == null ? 0 : Integer.parseInt(item.get("online_user_total").toString());
                    onlinePreHour.setOnlineUserCnt(onlineCnt);
                    onlinePreHour.setWarningFlag(onlineCnt < getTargetValue(allChatterConfigs, item) ? 1 : 0);
                    chatterOnlinePreHourDao.insert(onlinePreHour);
                }
            }
        }
    }

    private void addUserOnlineDetail() {
        final List<RptCustomQuerySqlEntity> onlineSqlList = getCustomSqlList(DataReportTypeEnum.ONLINE_USER_DETAIL.getType());
        final RptCustomQuerySqlEntity customQuerySql = onlineSqlList.get(0);
        final List<Map<String, Object>> records = cusomExtDao.customQuery2(customQuerySql.getSqlText());
        if (CollectionUtils.isEmpty(records)) {
            return;
        }

        final List<RptUserOnlineDetailEntity> existsRecords = userOnlineDetailDao.listUserOnline();

        // 当前时段用户数据
        List<RptUserOnlineDetailEntity> userOnlineList = Lists.newArrayList();
        for (Map<String, Object> item : records) {
            RptUserOnlineDetailEntity entity = new RptUserOnlineDetailEntity();
            String chatterCode = item.get("chatter_user_code").toString();
            String userCode = item.get("user_code").toString();
            final boolean noneMatch = existsRecords.parallelStream().noneMatch(o -> Objects.nonNull(o) && o.getChatterUserCode().equals(chatterCode) && o.getUserCode().equals(userCode)
                    && o.getCreateHour().equals(Integer.valueOf(item.get("create_hour").toString())));
            if (noneMatch) {
                entity.setCreateDt(Integer.valueOf(item.get("create_dt").toString()));
                entity.setCreateHour(Integer.valueOf(item.get("create_hour").toString()));
                entity.setChatterUserCode(chatterCode);
                entity.setUserCode(userCode);
                userOnlineList.add(entity);
            }
        }
        userOnlineDetailDao.batchInsert(userOnlineList);

    }

    private Map<String, RptChatterOnlinePreHourEntity> buildChatterOnlineMap() {
        final List<RptChatterOnlinePreHourEntity> onlinePreHourEntities = chatterOnlinePreHourDao.listChatterOnlinePreHour();
        if (CollectionUtils.isNotEmpty(onlinePreHourEntities)) {
            return onlinePreHourEntities.parallelStream().collect(Collectors.toMap(RptChatterOnlinePreHourEntity::getChatterUserCode, Function.identity()));
        }
        return Maps.newHashMap();
    }

    private Integer getTargetValue(List<ChatterConfigEntity> allChatterConfigs, Map<String, Object> item) {
        if (CollectionUtils.isNotEmpty(allChatterConfigs)) {
            return allChatterConfigs.parallelStream().filter(o -> o.getChatterCode().equals(item.get("chatter_user_code").toString())).filter(o -> o.getType() == 1).map(ChatterConfigEntity::getGoalValue).findFirst().orElse(0);
        }
        return 0;
    }

    /**
     * 封装更新语句
     */
    private String buildUpdateSql(RptCustomQuerySqlEntity customQuerySql, Map<String, Object> item) {
        if (CollectionUtils.isEmpty(item)) {
            return null;
        }
        String updateSqlStr = customQuerySql.getUpdateSqlText();
        final JSONObject updateSqlJson = JSONObject.parseObject(updateSqlStr);
        String updateSql = updateSqlJson.getString("updateSql");
        final String updateColumns = updateSqlJson.getString("updateColumn");
        try {

            if (StringUtils.isNotEmpty(updateColumns)) {
                final List<String> columns = Splitter.on(',').splitToList(updateColumns);
                for (String column : columns) {
                    updateSql = updateSql.replace("##" + column + "##", item.get(column) == null ? "0" : item.get(column).toString() );
                }
            }
            final String condition = updateSqlJson.getString("condition");
            if (StringUtils.isNotEmpty(condition)) {
                final List<String> conditionColumns = Splitter.on(',').splitToList(condition);
                for (String conditionColumn : conditionColumns) {
                    updateSql = updateSql.replace("##" + conditionColumn + "##", item.get(conditionColumn) == null ? "NoData" : item.get(conditionColumn).toString());
                }
            }
            logger.info("buildUpdateSql:{}", updateSql);
            return updateSql;
        } catch (Exception e) {
            logger.error("buildSqlError:{}, customQuerySql:{}", updateSql, JSONObject.toJSONString(customQuerySql), e);
        }
        return null;
    }


    private List<RptCustomQuerySqlEntity> getCustomSqlList(Integer type) {
        return customQuerySqlDao.listRptCustomQuerySqlByType(type);
    }

    private void initChatterData(List<UserInfoDto> chatters) {
        // 删除当天数据
        chatterDataPreDayDao.removeChatterData();
        // 初始化数据
        List<RptChatterDataPreDayEntity> chatterDataList = Lists.newArrayList();
        for (UserInfoDto chatter : chatters) {
            RptChatterDataPreDayEntity modelData = new RptChatterDataPreDayEntity();
            modelData.setChatterUserCode(chatter.getUserCode());
            modelData.setCreateDt(Integer.parseInt(DateUtil.getDate("yyyyMMdd")));
            chatterDataList.add(modelData);
        }
        // 批量插入当天model数据
        chatterDataPreDayDao.batchInsertData(chatterDataList);
    }
}
